package com.mt.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mt.enums.AclType;
import com.mt.enums.Status;
import com.mt.exception.GlobalException;
import com.mt.mapper.AclMapper;
import com.mt.pojo.Acl;
import com.mt.service.AclService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Wang
 * @since 2020-11-12
 */
@Service
@Slf4j
public class AclServiceImpl extends ServiceImpl<AclMapper, Acl> implements AclService {

    @Resource
    AclMapper aclMapper;

    @Override
    public Boolean addAcl(Acl acl) {
        if (validateAclParm(acl)) {
            if (aclMapper.insert(acl) == 0) {
                log.error("插入acl失败:{}", acl.toString());
                return false;
            }
        }
        log.info("新增权限成功");
        acl.getAclCode();
        return true;
    }

    @Override
    public Boolean isExistAcl(Acl acl) {
        Acl a = aclMapper.selectById(acl.getId());
        return a != null;
    }

    //扩展性不够好
    @Override
    public List<Acl> getAclTree() {
        List<Acl> acls = aclMapper.selectList(null);
        Map<Integer, Acl> rootMap = CollUtil.newHashMap();
        Map<Integer, Acl> menuMap = CollUtil.newHashMap();
//        利用stream流形式,parentId升序进行遍历
        acls.stream().sorted(Comparator.comparing(Acl::getParentId, Comparator.naturalOrder()))
                .forEach(acl -> {
                    if (acl.getParentId() == 0) {
                        rootMap.put(acl.getId(), acl);
                    } else {
                        //第二层的菜单
                        if (rootMap.containsKey(acl.getParentId())) {
                            List<Acl> childrenList = rootMap.get(acl.getParentId()).getChildren();
                            childrenList.add(acl);
                            menuMap.put(acl.getId(), acl);
                        } else if (menuMap.containsKey(acl.getParentId())) {
                            List<Acl> childrenList = menuMap.get(acl.getParentId()).getChildren();
                            childrenList.add(acl);
                        }
                    }
                });
        ArrayList<Acl> resultList = CollUtil.newArrayList(rootMap.values());
        return resultList;
    }

    // todo acl权限树的模糊搜索
    public List<Acl> getAclTree(String searcKey) {
        List<Acl> acls = aclMapper.selectList(Wrappers.<Acl>lambdaQuery().like(Acl::getAclName, searcKey));
        return acls;
    }

    @Override
    public Boolean deleteAcl(Acl acl) {
        if (aclMapper.deleteById(acl.getId()) > 0) {
            throw new GlobalException(Status.ERROR);
        }
        return true;
    }

    @Override
    public Boolean modifyAcl(Acl acl) {
        if (!isExistAcl(acl)) {
            throw new GlobalException(Status.NOT_EXIST_ACL);
        }
        validateAclParm(acl);
        aclMapper.updateById(acl);
        log.info("修改Acl:{}", acl.toString());
        return true;
    }

    @Override
    public Boolean validateAclParm(Acl acl) {
        if (acl.getAclName() == null) {
            throw new GlobalException(Status.ERROR, "ACL不可为空");
        }
        if (acl.getType().equals(AclType.getAclType("BUTTON")) && acl.getAclCode() == null) {
            throw new GlobalException(Status.ERROR, "ACL_CODE不可为空");
        }
        if (acl.getUrl() == null) {
            throw new GlobalException(Status.ERROR, "请求路径不可为空");
        }
        Acl aclName = aclMapper.selectOne(Wrappers.<Acl>lambdaQuery().eq(Acl::getAclName, acl.getAclName()));
        if (aclName != null) {
            throw new GlobalException(Status.EXIST_ACL_NAME);
        }
        if (acl.getAclCode() != null) {
            Acl aclCode = aclMapper.selectOne(Wrappers.<Acl>lambdaQuery().eq(Acl::getParentId, acl.getParentId())
                    .eq(Acl::getAclCode, acl.getAclCode()));
            if (aclCode != null) {
                throw new GlobalException(Status.EXIST_ACL_CODE);
            }
        }
        Acl aclPath = aclMapper.selectOne(Wrappers.<Acl>lambdaQuery().eq(Acl::getUrl, acl.getUrl())
                .eq(Acl::getRequestType, acl.getRequestType()));
        if (aclPath != null) {
            throw new GlobalException(Status.EXIST_ACL_PATH);
        }

        return true;
    }


}
